#include <iostream>
#include <cstring>
#include <cmath>

#include "Types.h"
#include "BigVector.h"

using namespace std;



void CompletizeBigVector (Array<Real> *a, int n)
{
	int prevsize = a->Size();
	a->SetSize (n);
	for (int i=prevsize; i<  n; i++)
		(*a)[i]=0.0;
}

extern "C" {

	void BigVectorSaxpy (Real * dest, Real a, Real const *x, Real const *y, int n)
	{
		for (; n--; )
		{
			*dest++ = a * (*x++  ) + (*y++);
		}
	}

	Real BigVectorIP (Real const * p1, Real const * p2, int n)
	{
		Real  const * e1 = p1 + n;

		Real i =0.0;
		while (p1 < e1)
		{
			i += (*p1++) * (*p2++);
		}
		return i;
	}


	void BigVectorPrint (Real const *ar, int n)
	{
		for (int i = 0 ;  i < n ; i++)
			cout << ((i && (i % 3)==0)? " | " : "") << " " << ar[i];
		cout << endl;
	}




	void BigVectorNullify (Real *ar, int n)
	{
		memset (ar, 0, n*sizeof (Real));
	}


	void BigVectorAdd (Real  * dest, Real const * p1, Real const * p2, int n)
	{
		for (; n--; )
		{
			*dest ++ = *p1++ + *p2++;
		}
	}

	void BigVectorSubtract (Real  * dest, Real const * p1, Real const * p2, int n)
	{
		for (; n--; )
		{
			*dest ++ = *p1++ - *p2++;
		}
	}

	void BigVectorPointwiseMultiply (Real  * dest, Real const * p1, Real const * p2, int n)
	{
		for (; n--; )
		{
			*dest ++ = *p1++ * *p2++;
		}
	}



	void BigVectorNegate (Real *dest, Real const*src, int n)
	{
		for (; n--; )
			*dest++ = - *src ++;
	}

	void BigVectorCopy (Real * d , Real const *s , int n)
	{
		memcpy  (d, s, n*sizeof (Real));
	}

	void BigVectorPointwiseInverse (Real *d, Real const * s, int n)
	{
		for (; n--; )
		{
			*d++ = 1 / (*s++);
		}
	}

	void BigVectorFill (Real * d, Real f , int n)
	{
		for (;n--;)
			*d++ = f;
	}

	void BigVectorScale (Real * d, Real s, Real *src, int n)
	{
		for (; n--; )
		{
			*d++ = s * (*src++);
		}
	}

	/*
	Copy SRC to DEST, leaving alone those entries that have ONOFF set to true
	*/
	void BigVectorPartialCopy (Real *dest, bool const*onoff, Real const *src,int n)
	{
		for (; n--; )
		{
			if (! *onoff++)
			{
				*dest = *src;
			}

			dest++;
			src ++;
		} 
	}

	/*
	Copy SRC to DEST, setting to 0.0 those entries that have ONOFF set to true.
	*/
	void BigVectorPartialNullify (Real * dest, Real const *src, bool const * onoff,  int n)
	{
		for (; n--; )
		{
			*dest++ = *onoff++ ? 0.0 : (*src );
			src ++;
		}
	}


	Real BigVectorLength (Real const * s, int n)
	{
		return sqrt (BigVectorIP (s,s,n) * n / 3);
	}

	Real BigVectorDistance (Real const * a, Real  const *b, int n)
	{
		Real s =0.0;
		while (n--)
		{
			Real d =  (*a++ - *b++);
			s+= d*d;
		}

		return sqrt (s);
	}

	Real BigVector1Norm (Real const * a , int n)
	{
		Real norm = 0.0;
		while (n--)
			norm += fabs (*a++);
		return norm;

	}

	bool BigVectorSane (Real const * a , int n)
	{
		bool b = true;
		while (b && n--)
		{
			b = b && !isinf (*a) && !isnan (*a);
			a++;
		}
		return b;
	}



} // extern "C"
